/****************************************Copyright (c)*************************
**                               版权所有 (C), 2015-2020, 涂鸦科技
**
**                                 http://www.tuya.com
**
**--------------文件信息-------------------------------------------------------
**文   件   名: system.c
**描        述: wifi数据处理函数
**使 用 说 明 : 用户无需关心该文件实现内容
**
**
**--------------当前版本修订---------------------------------------------------
** 版    本: v1.0.1
** 日　  期: 2020年2月26日
** 修改人员: 周猛
** 协议版本: v1.1.1
** 描　  述: 1:产品信息新增tp字段和p字段
             2:修改product_info_update函数，新增参数ver来选择是否支持获取产品pid
               将组包格式由JSON格式换成sprintf，以减轻MCU资源压力
             3:增加带传入帧版本的串口数据发送函数wifi_uart_write_frame_ver
             4:在wifi_uart_service函数中，取消了串口数据对帧版本的校验

** 版    本: v1.0.0
** 日　  期: 2019年7月27日
** 修改人员: 陈力恒
** 协议版本: v1.1.1
** 描　  述: 1:gateway通用协议mcu_sdk初版
**-----------------------------------------------------------------------------
******************************************************************************/

#define SYSTEM_GLOBAL
#include "config.h"
#include "wifi.h"


SUBDEV_MANAGE_ST            subdev_manage;//子设备管理结构体
unsigned short firm_size;                                                      //升级包一包的大小

/*设备能力选择*/
/*请在此处选择需要开启的设备的能力，ON为开启，OFF为关闭*/
tSUB_ABILITY sub_ability = {
      OFF,        //本地群组
      OFF,        //本地场景
      ON,        //网关有功能dp
      OFF,        //sigmesh
      ON,        //支持mcu升级
      OFF         //群组控制指令带sub_id
};



/*****************************************************************************
函数名称 : set_wifi_uart_byte
功能描述 : 写wifi_uart字节
输入参数 : dest:缓存区其实地址;
           byte:写入字节值
返回参数 : 写入完成后的总长度
*****************************************************************************/
unsigned short set_wifi_uart_byte(unsigned short dest, unsigned char byte)
{
  unsigned char *obj = (unsigned char *)wifi_uart_tx_buf + DATA_START + dest;
  
  *obj = byte;
  dest += 1;
  
  return dest;
}

/*****************************************************************************
函数名称 : set_wifi_uart_buffer
功能描述 : 写wifi_uart_buffer
输入参数 : dest:
           src:源地址（需要发送的数据）
           len:需要发送的数据长度
返回参数 : 写入buf的长度的长度
*****************************************************************************/
unsigned short set_wifi_uart_buffer(unsigned short dest, unsigned char *src, unsigned short len)
{
  unsigned char *obj = (unsigned char *)wifi_uart_tx_buf + DATA_START + dest;
  
  my_memcpy(obj,src,len);
  
  dest += len;
  return dest;
}

/*****************************************************************************
函数名称 : wifi_uart_write_data
功能描述 : 向wifi uart写入连续数据
输入参数 : in:发送缓存指针
           len:数据发送长度
返回参数 : 无
*****************************************************************************/
static void wifi_uart_write_data(unsigned char *in, unsigned short len)
{
  if((NULL == in) || (0 == len))
  {
    return;
  }
  
  while(len --)
  {
    uart_transmit_output(*in);
    in ++;
  }
}

/*****************************************************************************
函数名称 : get_check_sum
功能描述 : 计算校验和
输入参数 : pack:数据源指针
           pack_len:计算校验和长度
返回参数 : 校验和
*****************************************************************************/
unsigned char get_check_sum(unsigned char *pack, unsigned short pack_len)
{
  unsigned short i;
  unsigned char check_sum = 0;
  
  for(i = 0; i < pack_len; i ++)
  {
    check_sum += *pack ++;
  }
  
  return check_sum;
}

/*****************************************************************************
函数名称 : wifi_uart_write_frame
功能描述 : 向wifi串口发送一帧数据
输入参数 : fr_type:帧类型
           len:数据长度
返回参数 : 无
*****************************************************************************/
void wifi_uart_write_frame(unsigned char fr_type, unsigned short len)
{
  unsigned char check_sum = 0;
  
  wifi_uart_tx_buf[HEAD_FIRST] = 0x55;
  wifi_uart_tx_buf[HEAD_SECOND] = 0xaa;
  wifi_uart_tx_buf[PROTOCOL_VERSION] = 0x00;
  wifi_uart_tx_buf[FRAME_TYPE] = fr_type;
  wifi_uart_tx_buf[LENGTH_HIGH] = len >> 8;
  wifi_uart_tx_buf[LENGTH_LOW] = len & 0xff;
  
  len += PROTOCOL_HEAD;
  check_sum = get_check_sum((unsigned char *)wifi_uart_tx_buf, len - 1);
  wifi_uart_tx_buf[len - 1] = check_sum;
  //
  wifi_uart_write_data((unsigned char *)wifi_uart_tx_buf, len);
}

/*****************************************************************************
函数名称 : wifi_uart_write_frame_ver
功能描述 : 向wifi串口发送一帧数据
输入参数 : fr_type:帧类型
           len:数据长度
           fr_ver:帧版本
返回参数 : 无
*****************************************************************************/
void wifi_uart_write_frame_ver(unsigned char fr_type, unsigned short len, unsigned char fr_ver)
{
  unsigned char check_sum = 0;
  
  wifi_uart_tx_buf[HEAD_FIRST] = 0x55;
  wifi_uart_tx_buf[HEAD_SECOND] = 0xaa;
  wifi_uart_tx_buf[PROTOCOL_VERSION] = fr_ver;
  wifi_uart_tx_buf[FRAME_TYPE] = fr_type;
  wifi_uart_tx_buf[LENGTH_HIGH] = len >> 8;
  wifi_uart_tx_buf[LENGTH_LOW] = len & 0xff;
  
  len += PROTOCOL_HEAD;
  check_sum = get_check_sum((unsigned char *)wifi_uart_tx_buf, len - 1);
  wifi_uart_tx_buf[len - 1] = check_sum;
  //
  wifi_uart_write_data((unsigned char *)wifi_uart_tx_buf, len);
}

/*****************************************************************************
函数名称  : product_info_update
功能描述  : 产品信息上传
          
输入参数 : 无
返回参数 : 无
*****************************************************************************/
static void product_info_update(unsigned char ver)
{
  unsigned char length = 0;

  char out[60]; 
  if(0x01 == ver){
    sprintf(out,"{\"v\":\"%s\",\"m\":%d,\"cap\":%d,\"tp\":%d,\"p\":\"%s\"}",MCU_VER,CONFIG_MODE,sub_ability.whole,ACCESS_SUBDEV_TYPE,PRODUCT_KEY);
    gd_printf(("fun:%s-line:%d:out is:%s\r\n",__FUNCTION__,__LINE__,out));
  }else{
    sprintf(out,"{\"v\":\"%s\",\"m\":%d,\"cap\":0x%02}",MCU_VER,CONFIG_MODE,sub_ability.whole);
  }
  
  length = set_wifi_uart_buffer(length,out, my_strlen(out));

  wifi_uart_write_frame_ver(PRODUCT_INFO_CMD, length, ver);

  mem_free(out);
}

/*****************************************************************************
函数名称 : get_mcu_wifi_mode
功能描述 : 查询mcu和wifi的工作模式
输入参数 : 无
返回参数 : 无
*****************************************************************************/
static void get_mcu_wifi_mode(void)
{
  unsigned char length = 0;
  
#ifdef WIFI_CONTROL_SELF_MODE                                   //模块自处理
  length = set_wifi_uart_byte(length, WF_LED_PORT);
  length = set_wifi_uart_byte(length, WF_LED_PIN);
  length = set_wifi_uart_byte(length, WF_RESERT_KEY_PORT);
  length = set_wifi_uart_byte(length, WF_RESERT_KEY_PIN);
#else                                                           
  //无需处理数据
#endif
  
  wifi_uart_write_frame(WORK_MODE_CMD, length);
}

/*****************************************************************************
函数名称 : get_update_dpid_index
功能描述 : 获取制定DPID在数组中的序号
输入参数 : dpid:dpid
返回参数 : index:dp序号
*****************************************************************************/
static unsigned char get_dowmload_dpid_index(unsigned char dpid)
{
  unsigned char index;
  unsigned char total = get_download_cmd_total();
  
  for(index = 0; index < total; index++)
  {
    if(download_cmd[index].dp_id == dpid)
    {
      break;
    }
  }
  return index;
}

/*****************************************************************************
函数名称 : data_point_handle
功能描述 : 根据子设备id进行下发数据处理
输入参数 : value:下发数据源指针
           sub_id_buf：子设备的sun_id,决定数据发送置哪个子设备
返回参数 : ret:返回数据处理结果
*****************************************************************************/
static unsigned char data_point_handle(const unsigned char value[],unsigned char* sub_id_buf)
{
  //这边是数据下发函数，请根据实际情况调用
  unsigned char dp_id,index;
  unsigned char dp_type;
  unsigned char ret;
  unsigned short dp_len;
  
  dp_id = value[0];
  dp_type = value[1];
  dp_len = value[2] * 0x100;
  dp_len += value[3];
 
  if(0 == my_strcmp(sub_id_buf, "0000")) 
  { //"0000"代表的是需要进行下发数据处理的是网关本身

       index = get_dowmload_dpid_index(dp_id);
       if(dp_type != download_cmd[index].dp_type)
       {
         //错误提示
         gd_printf(("gateway type is wrong\r\n"));
         return FALSE;
       }
       else
       {
         ret = gw_dp_download_handle(dp_id,value + 4,dp_len);
       }
  }
  else 
  {                    //代表需要进行下发数据处理的是子设备，请根据dpid自行做出不同子设备的dp处理
                               //请根据sub_id来决定给哪个子设备下发数据
  
      //请在该函数根据子设备的id自行实现子设备的dpid处理
      ret = subdev_dp_download_handle(dp_id,value + 4,dp_len,sub_id_buf);
  }
    
    return ret;
}

/*****************************************************************************
函数名称 : data_handle
功能描述 : 数据帧处理
输入参数 : offset:数据起始位
返回参数 : 无
*****************************************************************************/
void data_handle(unsigned short offset)
{
  unsigned char *firmware_addr;
  static unsigned long firm_length;                          //MCU升级文件长度
  static unsigned char firm_update_flag;                     //MCU升级标志
  unsigned long dp_len_up;                                   //mcu升级的dplen
  unsigned char firm_flag;                                                      //升级包大小标志

  unsigned short dp_len;

  unsigned char ret;
  unsigned short i,total_len;
  unsigned char cmd_type = wifi_uart_rx_buf[offset + FRAME_TYPE];
  unsigned short length = 0;

  /*子设备id和群组id*/
  unsigned char sub_id_len = 0;                              //子设备id长度
  unsigned char grp_id_len = 0;                              //群组id长度
  unsigned char grp_id_buf[BUF_SIZE];                        //群组id
  unsigned char sub_id_buf[BUF_SIZE];                        //子设备id

  unsigned char *dest;
  unsigned int module_memory;

#ifdef WIFI_TEST_ENABLE
  unsigned char result;
  unsigned char rssi;
#endif
  gd_printf(("uart recv cmd=0x%02x\r\n", cmd_type));
  switch(cmd_type)
  {
  case PRODUCT_INFO_CMD:                                //产品信息
    product_info_update(wifi_uart_rx_buf[offset + PROTOCOL_VERSION]);
    break;
    
  case WORK_MODE_CMD:                                   //查询MCU设定的模块工作模式
    get_mcu_wifi_mode();
    break;
    
#ifndef WIFI_CONTROL_SELF_MODE
  case WIFI_STATE_CMD:                                  //wifi工作状态	
    wifi_work_state = wifi_uart_rx_buf[offset + DATA_START]; //记录模块当前工作方式
    gd_printf(("wifi state=%d\r\n", wifi_work_state));
    if(wifi_work_state==WIFI_NOT_CONNECTED)
    {
       gd_printf(("here is wifi not connect\r\n"));
    }
    else if(wifi_work_state==WIFI_CONNECTED||wifi_work_state==WIFI_CONN_CLOUD)
    {
       
       if(wifi_work_state==WIFI_CONN_CLOUD)
       {
          mcu_get_system_time();
          //mcu_get_green_time();
          gd_printf(("here is connect cloud\r\n"));
       }
       else
       {
          gd_printf(("here is connect wifi\r\n"));
       }
    }
    wifi_uart_write_frame(WIFI_STATE_CMD,0);
    break;

  case WIFI_RESET_CMD:                                  //重置wifi(wifi返回成功)
    reset_wifi_flag = RESET_WIFI_SUCCESS;
    break;
    
  case WIFI_MODE_CMD:                                   //选择smartconfig/AP模式(wifi返回成功)	
    set_wifimode_flag = SET_WIFICONFIG_SUCCESS;
    gd_printf(("change wifi net mode success\r\n"));
    break;
#endif

  case PERMIT_SUBDEVICE_NETIN_CMD:                      //允许子设备入网
    //TRUE则说明子设备允许入网，用户可根据这个标志位判断子设备是否允许入网
    subdev_manage.if_subdev_net_in = TRUE;
    start_subdev_searching_or_abort();
    wifi_uart_write_frame(PERMIT_SUBDEVICE_NETIN_CMD,0);
    gd_printf(("allow sub dev join gateway\r\n"));
    break;

  case CLOSE_SUBDEVICE_NETIN_CMD:                       //关闭子设备入网
    //FALSE说明拒绝子设备入网，用户可根据这个标志位判断子设备是否允许入网
    subdev_manage.if_subdev_net_in = FALSE;
    subdev_out_search_bind_mode();
    wifi_uart_write_frame(CLOSE_SUBDEVICE_NETIN_CMD,0);
    gd_printf(("close sub dev join gateway\r\n"));
    break;

  case SUBDEVICE_ADD_CMD:                               //子设备添加
    result = wifi_uart_rx_buf[offset + DATA_START];
    subdevice_add_result(result);
  break;

  case SUBDEVICE_DELETTE_CMD:                           //子设备删除
    total_len = wifi_uart_rx_buf[offset + LENGTH_HIGH] * 0x100;
    total_len += wifi_uart_rx_buf[offset + LENGTH_LOW];
    subdevice_delete((unsigned char *)&wifi_uart_rx_buf[offset + DATA_START],total_len);
    wifi_uart_write_frame(SUBDEVICE_DELETTE_CMD,0);
  break;

  case HEART_CHECK_CMD:                                 //心跳检测
    total_len = wifi_uart_rx_buf[offset + LENGTH_HIGH] * 0x100;
    total_len += wifi_uart_rx_buf[offset + LENGTH_LOW];
    heart_beat_check((unsigned char *)&wifi_uart_rx_buf[offset + DATA_START],total_len);
  break;
    
  case STATE_QUERY_CMD:                                 //状态查询
    all_data_update();                               
  break;

  case DATA_ISSUED_CMD:                                 //命令下发
    total_len = wifi_uart_rx_buf[offset + LENGTH_HIGH] * 0x100;
    total_len += wifi_uart_rx_buf[offset + LENGTH_LOW];
    sub_id_len = wifi_uart_rx_buf[offset + DATA_START];
    
    my_memset(sub_id_buf, 0x00, BUF_SIZE);
    my_memcpy(sub_id_buf, (unsigned char *)&wifi_uart_rx_buf[offset + DATA_START + 1], sub_id_len);
    
    for(i = 1 + sub_id_len;i < total_len;)
    {
      dp_len = wifi_uart_rx_buf[offset + DATA_START + i + 2] * 0x100;
      dp_len += wifi_uart_rx_buf[offset + DATA_START + i + 3];

      ret = data_point_handle((unsigned char *)wifi_uart_rx_buf + offset + DATA_START + i,sub_id_buf);

      if(SUCCESS == ret)
      {
        //成功提示
      }
      else
      {
        //错误提示
      }
      
      i += (dp_len + 4);
    }
  break;
  
#ifdef SUPPORT_GREEN_TIME
  case GET_ONLINE_TIME_CMD:                              //获取格林时间
    mcu_get_greentime((unsigned char *)(wifi_uart_rx_buf + offset + DATA_START));
  break;
#endif
  
#ifdef SUPPORT_MCU_RTC_CHECK
  case GET_LOCAL_TIME_CMD:                               //获取本地时间
    mcu_write_rtctime((unsigned char *)(wifi_uart_rx_buf + offset + DATA_START));
  break;
#endif

  case BATCH_ADD_DEV_CMD:                                //批量添加设备
    result = wifi_uart_rx_buf[offset + DATA_START];
    batch_add_dev_result(result);
  break;

  case ADD_DEV_RESULT_CMD:                               //返回添加设备结果
    total_len = wifi_uart_rx_buf[offset + LENGTH_HIGH] * 0x100;
    total_len += wifi_uart_rx_buf[offset + LENGTH_LOW];
  
    add_dev_result_get((unsigned char *)&wifi_uart_rx_buf[offset + DATA_START],total_len);
  break;

  #ifdef WIFI_TEST_ENABLE
    case WIFI_TEST_CMD:                                   //wifi功能测试（扫描指定路由）
      result = wifi_uart_rx_buf[offset + DATA_START];
      rssi = wifi_uart_rx_buf[offset + DATA_START + 1];
    
      wifi_test_result(result, rssi);
      break;
  #endif

  case GET_WIFI_STATUS_CMD:                               //获取wifi状态
      result = wifi_uart_rx_buf[offset + DATA_START];
      wifi_status_result(result);
    break;

  case INFORM_DEV_DEV_DEL_CMD:                            //报告移除状态
    result = wifi_uart_rx_buf[offset + DATA_START];
    inform_dev_del_status(result);
  break;

  case LOCAL_SUBDEV_DEL_CMD:                              //本地删除子设备
    result = wifi_uart_rx_buf[offset + DATA_START];
    local_del_subdev(result);
  break;

  case LOCAL_ADD_SUBDEV_LIMIT_CMD:                        //本地允许/关闭添加子设备
    result = wifi_uart_rx_buf[offset + DATA_START];
    local_subdev_limit(result);
  break;

  case GET_MODULE_REMAIN_MEMORY_CMD:                      //获取模块内存
    module_memory = wifi_uart_rx_buf[offset + DATA_START] << 3;
    module_memory += wifi_uart_rx_buf[offset + DATA_START + 1] << 2;
    module_memory += wifi_uart_rx_buf[offset + DATA_START + 2] << 1;
    module_memory += wifi_uart_rx_buf[offset + DATA_START + 3] << 0;

    remain_memory_result(module_memory);
  break;

  case QUR_SUBDEV_LIST:                                   //查询子设备列表
    total_len = wifi_uart_rx_buf[offset + LENGTH_HIGH] * 0x100;
    total_len += wifi_uart_rx_buf[offset + LENGTH_LOW];
    
    dest = (unsigned char*)mem_malloc(total_len);
    //dest = (unsigned char*)malloc(total_len);
    if(NULL == dest) {
      printf("malloc fail\n");
      return;
    }
    my_memset(dest,0,total_len);
    
    my_memcpy(dest, (unsigned char *)&wifi_uart_rx_buf[offset + DATA_START], total_len);
    
    local_subdev_list((unsigned char *)dest,total_len);
    mem_free(dest);
  break;

#ifdef SUPPORT_MCU_FIRM_UPDATE
    case UPDATE_START_CMD:                                //升级开始
      //升级包单包大小
      firm_flag = PACKAGE_SIZE;
      if(firm_flag == 0) {
        firm_size = 256;
      }else if(firm_flag == 1) {
        firm_size = 512;
      }else if(firm_flag == 2) { 
        firm_size = 1024;
      }

      //升级文件大小
      firm_length = wifi_uart_rx_buf[offset + DATA_START];
      firm_length <<= 8;
      firm_length |= wifi_uart_rx_buf[offset + DATA_START + 1];
      firm_length <<= 8;
      firm_length |= wifi_uart_rx_buf[offset + DATA_START + 2];
      firm_length <<= 8;
      firm_length |= wifi_uart_rx_buf[offset + DATA_START + 3];

      upgrade_package_choose(PACKAGE_SIZE);
      firm_update_flag = UPDATE_START_CMD;
       break;

    case UPDATE_TRANS_CMD:                                //升级传输
      if(firm_update_flag == UPDATE_START_CMD)
      {
        //停止一切数据上报
        stop_update_flag = ENABLE;                                                 

        //一包数据总长度
        total_len = wifi_uart_rx_buf[offset + LENGTH_HIGH] * 0x100;
        total_len += wifi_uart_rx_buf[offset + LENGTH_LOW];

        //包偏移
        dp_len_up = wifi_uart_rx_buf[offset + DATA_START];
        dp_len_up <<= 8;
        dp_len_up |= wifi_uart_rx_buf[offset + DATA_START + 1];
        dp_len_up <<= 8;
        dp_len_up |= wifi_uart_rx_buf[offset + DATA_START + 2];
        dp_len_up <<= 8;
        dp_len_up |= wifi_uart_rx_buf[offset + DATA_START + 3];

        //数据包
        firmware_addr = (unsigned char *)wifi_uart_rx_buf;
        firmware_addr += (offset + DATA_START + 4);  //数据包内容起始地址
        //没有数据内容或者包偏移等于升级文件大小（数据发送完成）
        if((total_len == 4) && (dp_len_up == firm_length))
        {
          //最后一包（代表数据发送完成）
          ret = mcu_firm_update_handle(firmware_addr,dp_len_up,0);
          
          firm_update_flag = 0;
        }
        else if((total_len - 4) <= firm_size) //数据pack里面还有数据
        {
          //数据未发送完成，进行数据处理
          ret = mcu_firm_update_handle(firmware_addr,dp_len_up,total_len - 4);
        }
        else
        {
          firm_update_flag = 0;
          ret = ERROR;
        }

        if(ret == SUCCESS)
        {
          wifi_uart_write_frame(UPDATE_TRANS_CMD,0);
        }
        //恢复一切数据上报
        stop_update_flag = DISABLE;    
      }
      break;

    case SUBDEV_START_UPGRADE_CMD:                          //子设备启动升级
      //获取升级包大小全局变量
      firm_flag = PACKAGE_SIZE;
      if(firm_flag == 0) {
        firm_size = 256;
      }else if(firm_flag == 1) {
        firm_size = 512;
      }else if(firm_flag == 2) { 
        firm_size = 1024;
      }
      
      sub_id_len = wifi_uart_rx_buf[offset + DATA_START];
      
      my_memset(sub_id_buf, 0x00, BUF_SIZE);
      my_memcpy(sub_id_buf, (unsigned char *)&wifi_uart_rx_buf[offset + DATA_START + 1], sub_id_len);
      
      //用户根据子设备id选择要升级的子设备
      firm_length = wifi_uart_rx_buf[offset + DATA_START + 1 + sub_id_len];
      firm_length <<= 8;
      firm_length |= wifi_uart_rx_buf[offset + DATA_START + 1 + 1 + sub_id_len];
      firm_length <<= 8;
      firm_length |= wifi_uart_rx_buf[offset + DATA_START + 2 + 1 + sub_id_len];
      firm_length <<= 8;
      firm_length |= wifi_uart_rx_buf[offset + DATA_START + 3 + 1 + sub_id_len];
      
      subdev_upgrade_package_choose(PACKAGE_SIZE,sub_id_buf,sub_id_len);
      firm_update_flag = SUBDEV_START_UPGRADE_CMD;
      break;
  
    case SUBDEV_TRANS_CMD:                                  //子设备升级包传输
      if(firm_update_flag == SUBDEV_START_UPGRADE_CMD)
      {
        //停止一切数据上报
        stop_update_flag = ENABLE;

        total_len = wifi_uart_rx_buf[offset + LENGTH_HIGH] * 0x100;
        total_len += wifi_uart_rx_buf[offset + LENGTH_LOW];
        
        sub_id_len = wifi_uart_rx_buf[offset + DATA_START];
        my_memset(sub_id_buf, 0x00, BUF_SIZE);
        my_memcpy(sub_id_buf, (unsigned char *)&wifi_uart_rx_buf[offset + DATA_START + 1], sub_id_len);
        
        dp_len_up = wifi_uart_rx_buf[offset + DATA_START + 1 + sub_id_len];
        dp_len_up <<= 8;
        dp_len_up |= wifi_uart_rx_buf[offset + DATA_START + 1 + 1 + sub_id_len];
        dp_len_up <<= 8;
        dp_len_up |= wifi_uart_rx_buf[offset + DATA_START + 2 + 1 + sub_id_len];
        dp_len_up <<= 8;
        dp_len_up |= wifi_uart_rx_buf[offset + DATA_START + 3 + 1 + sub_id_len];
        
        firmware_addr = (unsigned char *)wifi_uart_rx_buf;
        firmware_addr += (offset + DATA_START + 4 + 1 + sub_id_len);  //数据包内容起始地址
        if((total_len == 4 + 1 + sub_id_len) && (dp_len_up == firm_length))
        {
          //最后一包
          ret = subdev_firm_update_handle(sub_id_buf,firmware_addr,dp_len_up,0);
          
          firm_update_flag = 0;
        }
        else if((total_len - 4 - sub_id_len - 1) <= firm_size)
        {
          ret = subdev_firm_update_handle(sub_id_buf,firmware_addr,dp_len_up,total_len - 4- sub_id_len - 1);
        }
        else
        {
          firm_update_flag = 0;
          ret = ERROR;
        }
        
        if(ret == SUCCESS)
        {
          wifi_uart_write_frame(SUBDEV_TRANS_CMD,0);
        }
        //恢复一切数据上报
        stop_update_flag = DISABLE;    
      }
      break;
#endif

    case QUR_SUBDEV_VER_CMD:                              //查询子设备版本号
      total_len = wifi_uart_rx_buf[offset + LENGTH_HIGH] * 0x100;
      total_len += wifi_uart_rx_buf[offset + LENGTH_LOW];

      qur_subdev_ver_get((unsigned char *)&wifi_uart_rx_buf[offset + DATA_START],total_len);
    break;
//===================================sigmesh扩展协议==========================================
  default:
    break;
  }
}

/*****************************************************************************
函数名称 : get_queue_total_data
功能描述 : 读取队列内数据
输入参数 : 无
返回参数 : 无
*****************************************************************************/
unsigned char get_queue_total_data(void)
{
  if(queue_in != queue_out)
    return 1;
  else
    return 0;
}

/*****************************************************************************
函数名称 : Queue_Read_Byte
功能描述 : 读取队列1字节数据
输入参数 : 无
返回参数 : 无
*****************************************************************************/
unsigned char Queue_Read_Byte(void)
{
  unsigned char value;
  
  if(queue_out != queue_in)
  {
    //有数据
    if(queue_out >= (unsigned char *)(wifi_queue_buf + sizeof(wifi_queue_buf)))
    {
      //数据已经到末尾
      queue_out = (unsigned char *)(wifi_queue_buf);
    }
    
    value = *queue_out ++;   
  }
  
  return value;
}

